import random
import threading
import time
from typing import List

from requests.exceptions import *
from spider.epark_park import EParkParkSpider
from spider.ydt_park import YdtParkSpider

import spider_config
from common.logger import logger
from manager.proxy_manager import ProxyManager
from manager.account_manager import AccountManager
from model.park_platform import ParkPlatform
from model.park_spider import ParkSpider
from model.result import Result

from spider.etcp_park import EtcpParkSpider
from spider.jie_park import JieParkSpider
from spider.su_park import SuParkSpider
from spider.yima_park import YimaParkSpider
from spider.aiboke_park import AibokeParkSpider
from spider.ymiot_park import YmiotParkSpider
from spider.yun_park import YunParkSpider
from spider.airun_park import AirunParkSpider
from OpenSSL.SSL import Error as SSLError
import common.http as http

from model.car_number import CarNumber
from model.error import (
    ParkSpiderError,
    ParkSpiderErrorCode,
    BannedAccountError,
    TokenExpireError,
)
from model.proxy import Proxy
from json import JSONDecodeError

from common.verify import verify_car_number


def build_spider(platform_id: int):
    if platform_id == spider_config.su_park_id:
        return SuParkSpider()
    elif platform_id == spider_config.etcp_park_id:
        return EtcpParkSpider()
    elif platform_id == spider_config.jie_park_id:
        return JieParkSpider()
    elif platform_id == spider_config.yima_park_id:
        return YimaParkSpider()
    elif platform_id == spider_config.aiboke_park_id:
        return AibokeParkSpider()
    elif platform_id == spider_config.ymiot_park_id:
        return YmiotParkSpider()
    elif platform_id == spider_config.yun_park_id:
        return YunParkSpider()
    elif platform_id == spider_config.ydt_park_id:
        return YdtParkSpider()
    elif platform_id == spider_config.epark_park_id:
        return EParkParkSpider()
    elif platform_id == spider_config.airun_park_id:
        return AirunParkSpider()
    else:
        raise ParkSpiderError(ParkSpiderErrorCode.InvavlidPlatform, platform_id)


class SpiderManager:
    def __init__(self) -> None:
        self.__proxy_manager: ProxyManager = None
        self.__proxy_lock = threading.RLock()
        self.__account_manager: AccountManager = None
        self.__account_lock = threading.RLock()
        self.__platform_id: int = None
        self.__spider: ParkSpider = None

    def set_platform(self, platform_id: int):
        self.__platform_id = platform_id
        self.__spider = build_spider(platform_id)

    def set_proxym_anager(self, proxy_manager: ProxyManager):
        self.__proxy_manager = proxy_manager

    def set_account_manager(self, account_manager: AccountManager):
        self.__account_manager = account_manager

    def get_account_manager(self):
        return self.__account_manager

    def take_account(self, platform_id: int):
        with self.__account_lock:
            return self.__account_manager.take_account(platform_id)

    def take_proxy(self, platform_id: int) -> Proxy:
        with self.__proxy_lock:
            return self.__proxy_manager.take_proxy(platform_id)

    def invalid_proxy(self, platform_id: int, proxy: Proxy):
        with self.__proxy_lock:
            self.__proxy_manager.invalid_proxy(platform_id, proxy)

    def invalid_account(self, platform_id: int, account):
        with self.__account_lock:
            if self.__account_manager.invalid_account(platform_id, account):
                logger.warning(
                    f"移除平台 {platform_id} 无效账号: {account}, 剩余账号数量: {self.__account_manager.account_count(platform_id)}"
                )

    def query_all(self, car_cumber: str, spiders: List[ParkSpider]) -> Result:
        for spider in spiders:
            result = self.query(car_cumber, spider)
            if result and result.success:
                return result
        return None

    def query(self, car_number: CarNumber, repeat_count: int = 0) -> Result:
        
        result = Result()
        result.car_number = car_number
        result.platform = ParkPlatform(self.__platform_id)

        proxy = self.take_proxy(self.__platform_id)
        account = self.take_account(self.__platform_id)
        
        try:
            if proxy.is_empty():
                self.__spider.setProxy(None)
            else:
                self.__spider.setProxy(proxy.build())
            self.__spider.setAccount(account)
            r = self.__spider.query(car_number)
            result.success = r.success
            result.message = r.message
            result.error_code = r.error_code
            result.enter_time = r.enter_time
            result.price = r.price
            result.park_name = r.park_name
            result.remark = r.remark
        except (
            ConnectTimeout,
            ConnectionError,
            RequestException,
            KeyError,
            ProxyError,
            JSONDecodeError,
            BannedAccountError,
            TokenExpireError,
            SSLError,
        ) as e:
            repeat_count += 1
            if repeat_count > 3:
                logger.error(f"查询失败: {car_number}，exception:{repr(e)}")
                return result
            if isinstance(e, ProxyError):
                self.invalid_proxy(self.__spider.platform().id, proxy)
            if isinstance(e, BannedAccountError) or isinstance(e, TokenExpireError):
                self.invalid_account(self.__spider.platform().id, account)
            # logger.debug(repr(e))
            return self.query(car_number, repeat_count)

        return result
